﻿/** \file
* \$Rev: 187 $
* 
* \$Date: 2010-04-27 21:58:51 +0000 (Tue, 27 Apr 2010) $
*
* \$URL: http://chorus-twitter.googlecode.com/svn/trunk/src/gui/AccountForm.cs $
*/

using System;
using System.Drawing;
using System.Windows.Forms;
using chorus.twitter;
using chorus.utils;

namespace chorus.gui
{
	/// <summary>
	/// The account form, responsible for adding and removing Twitter accounts,
	/// etc.
	/// </summary>
	public partial class AccountForm : Form
	{
		/// <summary>An object to bind a control to a Twitter colour specifier tag.</summary>
		public class BoundColour
		{
			/// <summary>The control to which this colour is bound.</summary>
			Control control;
			/// <summary>The Twitter property tag with which this colour is associated.</summary>
			string tag;

			/// <summary>The constructor.</summary>
			/// <param name="control">The control to which this colour is bound.</param>
			/// <param name="tag">The Twitter property tag with which this colour is associated.</param>
			public BoundColour(Control control, string tag)
			{
				this.control = control;
				this.tag = tag;
			}

			/// <summary>Bind a control's background colour.</summary>
			/// <param name="source">The binding source that will change the colour.</param>
			/// <returns>The new binding.</returns>
			public Binding Bind(BindingSource source)
			{
				Binding binding = new Binding("BackColor", source, tag);
				control.DataBindings.Add(binding);
				return binding;
			}
		}

		/// <summary>The array of colour binding objects.</summary>
		BoundColour[] colours;
		/// <summary>The currently selected account.</summary>
		Account Active { get { return (Account)bindingAccount.Current; } }

		/// <summary>The constructor.</summary>
		public AccountForm()
		{
			InitializeComponent();
			bindingAccount.DataSource = Program.accounts;

			colours = new BoundColour[]
			{
				new BoundColour(buttonColourBack,       "profile_background_color"),
				new BoundColour(buttonColourText,       "profile_text_color"),
				new BoundColour(buttonColourLinks,      "profile_link_color"),
				new BoundColour(buttonColourSideBack,   "profile_sidebar_fill_color"),
				new BoundColour(buttonColourSideBorder, "profile_sidebar_border_color"),
			};

			foreach (BoundColour bc in colours)
			{
				Binding binding = bc.Bind(bindingAccount);
				binding.Format += new ConvertEventHandler(boundcolor_Format);
				binding.Parse += new ConvertEventHandler(boundcolor_Parse);
			}

			listAccounts.textName.KeyPress += new KeyPressEventHandler(textName_KeyPress);

			CheckEnables();
			listAccounts.Focus();
		}

		/// <summary>Enable several controls based on whether there's an account selected.</summary>
		void CheckEnables()
		{
			bool isActive = Active != null;
			groupSettings.Enabled = isActive;
			groupDelivery.Enabled = isActive;
			groupColours.Enabled = isActive;
			groupTransactions.Enabled = isActive;
			buttonPassword.Enabled = isActive;
			buttonDetails.Enabled = isActive;
		}

		/// <summary>A callback for when the account info is fetched.</summary>
		/// <param name="response">The response object.</param>
		void Deserialize(Account response)
		{
			Utils.InvokeControl(this, delegate()
			{
				if (response != null)
				{
					if (listAccounts.NameMode == RenameList<Account>.NameModeEnum.New)
						bindingAccount.Position = bindingAccount.Add(response);
					else
					{
						Active.MergeFrom(response);
						bindingAccount.ResetCurrentItem();
					}
				}
			});
		}

		#region Event handlers

		/// <summary>Fired when a key is pressed in the naming box.</summary>
		/// <param name="sender">The event sender.</param>
		/// <param name="e">The event parameters.</param>
		void textName_KeyPress(object sender, KeyPressEventArgs e)
		{
			if (!(user.ValidScreennameChar(e.KeyChar) || e.KeyChar == '\b'))
			{
				// Horrific 'beep' hack
				e.KeyChar = '\n';
			}
		}

		/// <summary>Fired when a new item is added to the account list.</summary>
		/// <param name="acc">The new item.</param>
		void listAccounts_Refresh(Account acc) {
			acc.RequestPassword();

			net.AccountSource source = new net.AccountSource();
			source.Auth = acc;
			source.FetchAsync(Deserialize);
		}

		/// <summary>Fired when the selected account changes.</summary>
		/// <param name="sender">The event sender.</param>
		/// <param name="e">The event parameters.</param>
		void bindingAccount_CurrentChanged(object sender, EventArgs e) { CheckEnables(); }

		/// <summary>Fired when a Twitter colour needs to be formatted from a serialized colour.</summary>
		/// <param name="sender">The event sender.</param>
		/// <param name="e">The event parameters; e.Value contains a SerColour.</param>
		void boundcolor_Format(object sender, ConvertEventArgs e)
		{
			e.Value = e.Value == null ? Color.FromKnownColor(KnownColor.Control) : ((SerColour)e.Value).val;
		}

		/// <summary>Fired when a Twitter serialized colour needs to be parsed from a colour.</summary>
		/// <param name="sender">The event sender.</param>
		/// <param name="e">The event parameters; e.Value contains a Color.</param>
		void boundcolor_Parse(object sender, ConvertEventArgs e)
		{
			SerColour colour = new SerColour();
			if (e.Value != null)
				colour.val = (Color)e.Value;
			e.Value = colour;
		}

		/// <summary>Fired when the user wishes to select a colour.</summary>
		/// <param name="sender">The event sender - this is a control that received the colour.</param>
		/// <param name="e">The event parameters.</param>
		void onChangeColour(object sender, EventArgs e)
		{
			ColorDialog dlg = new ColorDialog();
			if (dlg.ShowDialog() == DialogResult.OK)
				((Control)sender).BackColor = dlg.Color;
		}

		/// <summary>Fired when the user clicks on the password button.</summary>
		/// <param name="sender">The event sender.</param>
		/// <param name="e">The event parameters.</param>
		void buttonPassword_Click(object sender, EventArgs e) { listAccounts_Refresh(Active); }

		/// <summary>Fired when the user clicks on the preview button.</summary>
		/// <param name="sender">The event sender.</param>
		/// <param name="e">The event parameters.</param>
		void buttonDetails_Click(object sender, EventArgs e)
		{
			UserForm uform = new UserForm(Active);
			uform.ShowDialog(this);
		}

		/// <summary>Fired when the user clicks on the OK button.</summary>
		/// <param name="sender">The event sender.</param>
		/// <param name="e">The event parameters.</param>
		void buttonOk_Click(object sender, EventArgs e) { Close(); }

		#endregion
	}
}
